import { FormattedKlineData } from '../services/market-data.service';
import { AccountType } from './backtest-engine.service';

/**
 * 交易信号枚举
 * - BUY/SELL: 现货买入/卖出
 * - HOLD: 持仓观望
 * - OPEN_LONG/CLOSE_LONG: 合约开多/平多
 * - OPEN_SHORT/CLOSE_SHORT: 合约开空/平空
 */
export enum TradeSignal {
  BUY, SELL, HOLD, OPEN_LONG, CLOSE_LONG, OPEN_SHORT, CLOSE_SHORT,
}

/**
 * 仓位状态枚举
 * - NONE: 空仓
 * - LONG: 多头持仓
 * - SHORT: 空头持仓
 */
export enum PositionState {
  NONE, LONG, SHORT,
}

/**
 * 策略接口，所有策略需实现
 */
export interface IStrategy {
  /** 策略名称 */
  name: string;
  /** 指标预热期，回测时需加载的额外K线数量 */
  readonly warmupPeriod: number;
  /**
   * 初始化方法，回测前调用，传入历史K线数据（含预热期）
   * @param data 历史K线数据
   */
  initialize(data: FormattedKlineData[]): Promise<void>;
  /**
   * 每根K线调用，返回当前交易信号
   * @param kline 当前K线
   */
  update(kline: FormattedKlineData): TradeOrder;
}

/**
 * 交易指令对象
 * - signal: 交易信号
 * - price: 指定成交价格（如止损/止盈），可选
 */
export interface TradeOrder {
  signal: TradeSignal;
  price?: number;
}

/**
 * 策略基础配置
 * - accountType: 账户类型（现货/合约）
 * - leverage: 杠杆倍数（合约）
 * - longStopLossRate: 多头止损率
 * - shortStopLossRate: 空头止损率
 * - takeProfitRate: 止盈率
 */
export interface BaseStrategyConfig {
  accountType: AccountType;
  leverage?: number;
  longStopLossRate?: number;
  shortStopLossRate?: number;
  takeProfitRate?: number;
}

/**
 * 策略基类，封装常用止损/止盈等逻辑，便于子类继承
 */
export abstract class BaseStrategy implements IStrategy {
  /** 策略名称 */
  public abstract name: string;
  /** 指标预热期 */
  public abstract readonly warmupPeriod: number;

  /** 账户类型（现货/合约） */
  protected readonly accountType: AccountType;
  /** 杠杆倍数 */
  protected readonly leverage: number;
  /** 多头止损率 */
  protected readonly longStopLossRate: number;
  /** 空头止损率 */
  protected readonly shortStopLossRate: number;
  /** 止盈率 */
  protected readonly takeProfitRate: number;

  /** 合约持仓状态 */
  protected contractState: PositionState = PositionState.NONE;
  /** 现货最后信号 */
  protected spotLastSignal: TradeSignal = TradeSignal.HOLD;

  /** 当前持仓开仓价 */
  protected entryPrice: number | null = null;
  /** 当前止损价 */
  protected stopLossPrice: number | null = null;
  /** 当前止盈价 */
  protected takeProfitPrice: number | null = null;

  /**
   * 构造函数，初始化基础参数
   * @param config 策略基础配置
   */
  constructor(config: BaseStrategyConfig) {
    this.accountType = config.accountType;
    this.leverage = config.leverage || 1;
    this.longStopLossRate = config.longStopLossRate || 0;
    this.shortStopLossRate = config.shortStopLossRate || 0;
    this.takeProfitRate = config.takeProfitRate || 0;
  }

  /**
   * 初始化方法，子类需实现
   * @param data 历史K线数据
   */
  public abstract initialize(data: FormattedKlineData[]): Promise<void>;
  /**
   * 每根K线调用，返回交易指令，子类需实现
   * @param kline 当前K线
   */
  public abstract update(kline: FormattedKlineData): TradeOrder;

  /**
   * 计算合约止损价
   * @param entryPrice 开仓价
   * @param side 持仓方向
   * @param rate 止损率
   * @returns 止损触发价
   */
  protected calcContractStopLossPrice(entryPrice: number, side: PositionState, rate: number): number {
    if (rate <= 0) {
      return side === PositionState.LONG ? 0 : Infinity;
    }
    if (side === PositionState.LONG) {
      return entryPrice * (1 - rate / this.leverage);
    } else if (side === PositionState.SHORT) {
      return entryPrice * (1 + rate / this.leverage);
    }
    return entryPrice;
  }

  /**
   * 计算合约止盈价
   * @param entryPrice 开仓价
   * @param side 持仓方向
   * @param rate 止盈率
   * @returns 止盈触发价
   */
  protected calcContractTakeProfitPrice(entryPrice: number, side: PositionState, rate: number): number {
    if (rate <= 0) {
      return side === PositionState.LONG ? Infinity : 0;
    }
    if (side === PositionState.LONG) {
      return entryPrice * (1 + rate / this.leverage);
    } else if (side === PositionState.SHORT) {
      return entryPrice * (1 - rate / this.leverage);
    }
    return entryPrice;
  }

  /**
   * 检查是否触发止损，若触发则返回平仓指令
   * @param kline 当前K线
   */
  protected checkStopLoss(kline: FormattedKlineData): TradeOrder {
    const isLong = this.contractState === PositionState.LONG || this.spotLastSignal === TradeSignal.BUY;
    const isShort = this.contractState === PositionState.SHORT;
    const currentRate = isLong ? this.longStopLossRate : (isShort ? this.shortStopLossRate : 0);

    if (this.entryPrice === null || this.stopLossPrice === null || currentRate <= 0) {
      return { signal: TradeSignal.HOLD };
    }

    const resetStopLossState = () => {
      this.entryPrice = null;
      this.stopLossPrice = null;
      this.takeProfitPrice = null;
    };

    const stopPrice = this.stopLossPrice;

    // 多头止损
    if (isLong && kline.low <= this.stopLossPrice) {
      resetStopLossState();
      if (this.accountType === AccountType.CONTRACT) {
        this.contractState = PositionState.NONE;
        console.log(`[STOP-LOSS] 多头止损触发，价格: ${kline.low.toFixed(4)} (止损线: ${stopPrice.toFixed(4)})`);
        return { signal: TradeSignal.CLOSE_LONG, price: stopPrice };
      } else {
        this.spotLastSignal = TradeSignal.SELL;
        console.log(`[STOP-LOSS] 现货止损卖出，价格: ${kline.low.toFixed(4)} (止损线: ${stopPrice.toFixed(4)})`);
        return { signal: TradeSignal.SELL, price: stopPrice };
      }
    }

    // 空头止损
    if (isShort && kline.high >= this.stopLossPrice) {
      resetStopLossState();
      this.contractState = PositionState.NONE;
      console.log(`[STOP-LOSS] 空头止损触发，价格: ${kline.high.toFixed(4)} (止损线: ${stopPrice.toFixed(4)})`);
      return { signal: TradeSignal.CLOSE_SHORT, price: stopPrice };
    }

    return { signal: TradeSignal.HOLD };
  }

  /**
   * 检查是否触发止盈，若触发则返回平仓指令
   * @param kline 当前K线
   */
  protected checkTakeProfit(kline: FormattedKlineData): TradeOrder {
    if (this.entryPrice === null || this.takeProfitPrice === null || this.takeProfitRate <= 0) {
      return { signal: TradeSignal.HOLD };
    }

    const resetTakeProfitState = () => {
      this.entryPrice = null;
      this.stopLossPrice = null;
      this.takeProfitPrice = null;
    };

    const takeProfitPrice = this.takeProfitPrice;

    // 多头止盈
    if ((this.contractState === PositionState.LONG || this.spotLastSignal === TradeSignal.BUY) && kline.high >= this.takeProfitPrice) {
      resetTakeProfitState();
      if (this.accountType === AccountType.CONTRACT) {
        this.contractState = PositionState.NONE;
        console.log(`[TAKE-PROFIT] 多头止盈触发，价格: ${kline.high.toFixed(4)} (止盈线: ${takeProfitPrice.toFixed(4)})`);
        return { signal: TradeSignal.CLOSE_LONG, price: takeProfitPrice };
      } else {
        this.spotLastSignal = TradeSignal.SELL;
        console.log(`[TAKE-PROFIT] 现货止盈卖出，价格: ${kline.high.toFixed(4)} (止盈线: ${takeProfitPrice.toFixed(4)})`);
        return { signal: TradeSignal.SELL, price: takeProfitPrice };
      }
    }

    // 空头止盈
    if (this.contractState === PositionState.SHORT && kline.low <= this.takeProfitPrice) {
      resetTakeProfitState();
      this.contractState = PositionState.NONE;
      console.log(`[TAKE-PROFIT] 空头止盈触发，价格: ${kline.low.toFixed(4)} (止盈线: ${takeProfitPrice.toFixed(4)})`);
      return { signal: TradeSignal.CLOSE_SHORT, price: takeProfitPrice };
    }

    return { signal: TradeSignal.HOLD };
  }
}
